diff --git a/pkg/providers/v1/aws.go b/pkg/providers/v1/aws.go
index 39dab8f..af8217e 100644
--- a/pkg/providers/v1/aws.go
+++ b/pkg/providers/v1/aws.go
@@ -310,6 +310,13 @@ var backendProtocolMapping = map[string]string{
 	"tcp":   "ssl",
 }

+var backendProtocolToAwsEnumMapping = map[string]string{
+	"tcp":   elbv2.ProtocolEnumTcp,
+	"tls":   elbv2.ProtocolEnumTls,
+	"http":  elbv2.ProtocolEnumHttp,
+	"https": elbv2.ProtocolEnumHttps,
+}
+
 // MaxReadThenCreateRetries sets the maximum number of attempts we will make when
 // we read to see if something exists and then try to create it if we didn't find it.
 // This can fail once in a consistent system if done in parallel
@@ -3992,7 +3999,7 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
 			continue
 		}

-		if isNLB(annotations) {
+		if isNLB(annotations) || isNone(annotations) {
 			portMapping := nlbPortMapping{
 				FrontendPort:     int64(port.Port),
 				FrontendProtocol: string(port.Protocol),
@@ -4003,7 +4010,11 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
 			if portMapping.HealthCheckConfig, err = c.buildNLBHealthCheckConfiguration(apiService); err != nil {
 				return nil, err
 			}
-
+			if isNone(annotations) {
+				portMapping.HealthCheckConfig.Protocol = elbv2.ProtocolEnumHttp
+				portMapping.HealthCheckConfig.Port = "10256" // ProxyHealthzPort
+				portMapping.HealthCheckConfig.Path = "/healthz"
+			}
 			certificateARN := annotations[ServiceAnnotationLoadBalancerCertificate]
 			if port.Protocol != v1.ProtocolUDP && certificateARN != "" && (sslPorts == nil || sslPorts.numbers.Has(int64(port.Port)) || sslPorts.names.Has(port.Name)) {
 				portMapping.FrontendProtocol = elbv2.ProtocolEnumTls
@@ -4014,7 +4025,18 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
 					portMapping.TrafficProtocol = elbv2.ProtocolEnumTls
 				}
 			}
-
+			if isNone(annotations) {
+				instanceProtocol := annotations[ServiceAnnotationLoadBalancerBEProtocol]
+				if instanceProtocol == "" {
+					portMapping.TrafficProtocol = backendProtocolToAwsEnumMapping["tcp"]
+				} else {
+					protocol := backendProtocolToAwsEnumMapping[instanceProtocol]
+					if protocol == "" {
+						return nil, fmt.Errorf("invalid backend protocol %s", ServiceAnnotationLoadBalancerBEProtocol)
+					}
+					portMapping.TrafficProtocol = protocol
+				}
+			}
 			v2Mappings = append(v2Mappings, portMapping)
 		} else {
 			listener, err := buildListener(port, annotations, sslPorts)
@@ -4047,7 +4069,58 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
 	} else if internalAnnotation != "" {
 		internalELB = true
 	}
+	if isNone(annotations) {
+		if path, healthCheckNodePort := servicehelpers.GetServiceHealthCheckPathPort(apiService); path != "" {
+			for i := range v2Mappings {
+				v2Mappings[i].HealthCheckConfig.Port = strconv.Itoa(int(healthCheckNodePort))
+				v2Mappings[i].HealthCheckConfig.Path = path
+				v2Mappings[i].HealthCheckConfig.Protocol = elbv2.ProtocolEnumHttp
+			}
+		}
+
+		loadBalancerName := c.GetLoadBalancerName(ctx, clusterName, apiService)
+		serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name}

+		instanceIDs := []string{}
+		for id := range instances {
+			instanceIDs = append(instanceIDs, string(id))
+		}
+
+		// Get additional tags set by the user
+		tags := getKeyValuePropertiesFromAnnotation(annotations, ServiceAnnotationLoadBalancerAdditionalTags)
+		// Add default tags
+		tags[TagNameKubernetesService] = serviceName.String()
+		tags = c.tagging.buildTags(ResourceLifecycleOwned, tags)
+
+		for i, mapping := range v2Mappings {
+			tgNameWithSuffix := generateTgName(loadBalancerName, strconv.Itoa(i))
+			existingTg, err := c.describeTargetGroup(tgNameWithSuffix)
+			if err != nil {
+				return nil, err
+			}
+
+			_, err = c.ensureTargetGroup(
+				existingTg,
+				serviceName,
+				mapping,
+				instanceIDs,
+				c.vpcID,
+				tags,
+				tgNameWithSuffix,
+			)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		return &v1.LoadBalancerStatus{Ingress: []v1.LoadBalancerIngress{
+			{
+				IP:       "0.0.0.0",
+				Hostname: "none",
+			},
+		},
+		}, nil
+	}
 	if isNLB(annotations) {
 		// Find the subnets that the ELB will live in
 		subnetIDs, err := c.getLoadBalancerSubnets(apiService, internalELB)
@@ -4365,7 +4438,34 @@ func (c *Cloud) GetLoadBalancer(ctx context.Context, clusterName string, service
 		return nil, false, nil
 	}
 	loadBalancerName := c.GetLoadBalancerName(ctx, clusterName, service)
+	if isNone(service.Annotations) {
+		tgCount := 0
+		portCount := len(service.Spec.Ports)
+		for i, _ := range service.Spec.Ports {
+			tgNameWithSuffix := generateTgName(loadBalancerName, strconv.Itoa(i))
+			tg, err := c.describeTargetGroup(tgNameWithSuffix)
+			if err != nil {
+				return nil, false, err
+			}

+			if tg != nil {
+				tgCount++
+			}
+		}
+		if tgCount == 0 {
+			return nil, false, nil
+		} else if tgCount < portCount {
+			return nil, true, nil
+		} else {
+			return &v1.LoadBalancerStatus{[]v1.LoadBalancerIngress{
+				{
+					IP:       "0.0.0.0",
+					Hostname: "none",
+				},
+			},
+			}, true, nil
+		}
+	}
 	if isNLB(service.Annotations) {
 		lb, err := c.describeLoadBalancerv2(loadBalancerName)
 		if err != nil {
@@ -4629,6 +4729,25 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
 	}
 	loadBalancerName := c.GetLoadBalancerName(ctx, clusterName, service)

+	if isNone(service.Annotations) {
+		for i, _ := range service.Spec.Ports {
+			tgNameWithSuffix := generateTgName(loadBalancerName, strconv.Itoa(i))
+			tg, err := c.describeTargetGroup(tgNameWithSuffix)
+			if err != nil {
+				return err
+			}
+			if tg == nil {
+				klog.Info("Target group already deleted: ", loadBalancerName)
+			}
+
+			_, err = c.elbv2.DeleteTargetGroup(&elbv2.DeleteTargetGroupInput{TargetGroupArn: tg.TargetGroupArn})
+			if err != nil {
+				return err
+			}
+		}
+
+		return nil
+	}
 	if isNLB(service.Annotations) {
 		lb, err := c.describeLoadBalancerv2(loadBalancerName)
 		if err != nil {
@@ -4819,6 +4938,10 @@ func (c *Cloud) UpdateLoadBalancer(ctx context.Context, clusterName string, serv
 		return err
 	}
 	loadBalancerName := c.GetLoadBalancerName(ctx, clusterName, service)
+	if isNone(service.Annotations) {
+		_, err = c.EnsureLoadBalancer(ctx, clusterName, service, nodes)
+		return err
+	}
 	if isNLB(service.Annotations) {
 		lb, err := c.describeLoadBalancerv2(loadBalancerName)
 		if err != nil {
@@ -5183,6 +5306,10 @@ func getInitialAttachDetachDelay(status string) time.Duration {
 	return volumeAttachmentStatusInitialDelay
 }

+func generateTgName(prefix, suffix string) string {
+	return prefix[0:32-1-len(suffix)] + "-" + suffix
+}
+
 // describeNetworkInterfaces returns network interface information for the given DNS name.
 func (c *Cloud) describeNetworkInterfaces(nodeName string) (*ec2.NetworkInterface, error) {
 	eniEndpoint := strings.TrimPrefix(nodeName, fargateNodeNamePrefix)
diff --git a/pkg/providers/v1/aws_loadbalancer.go b/pkg/providers/v1/aws_loadbalancer.go
index 8f9884c..280caf1 100644
--- a/pkg/providers/v1/aws_loadbalancer.go
+++ b/pkg/providers/v1/aws_loadbalancer.go
@@ -87,6 +87,13 @@ func isLBExternal(annotations map[string]string) bool {
 	return false
 }

+func isNone(annotations map[string]string) bool {
+	if annotations[ServiceAnnotationLoadBalancerType] == "none" {
+		return true
+	}
+	return false
+}
+
 type healthCheckConfig struct {
 	Port               string
 	Path               string
@@ -137,6 +144,21 @@ func getKeyValuePropertiesFromAnnotation(annotations map[string]string, annotati
 	return additionalTags
 }

+func (c *Cloud) describeTargetGroup(tgName string) (*elbv2.TargetGroup, error) {
+	response, err := c.elbv2.DescribeTargetGroups(&elbv2.DescribeTargetGroupsInput{})
+	if err != nil {
+		return nil, fmt.Errorf("error describing target groups: %q", err)
+	}
+
+	for _, tg := range response.TargetGroups {
+		if *tg.TargetGroupName == tgName {
+			return tg, nil
+		}
+	}
+
+	return nil, nil
+}
+
 // ensureLoadBalancerv2 ensures a v2 load balancer is created
 func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBalancerName string, mappings []nlbPortMapping, instanceIDs, subnetIDs []string, internalELB bool, annotations map[string]string) (*elbv2.LoadBalancer, error) {
 	loadBalancer, err := c.describeLoadBalancerv2(loadBalancerName)
@@ -576,7 +598,7 @@ func (c *Cloud) deleteListenerV2(listener *elbv2.Listener) error {
 }

 // ensureTargetGroup creates a target group with a set of instances.
-func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName types.NamespacedName, mapping nlbPortMapping, instances []string, vpcID string, tags map[string]string) (*elbv2.TargetGroup, error) {
+func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName types.NamespacedName, mapping nlbPortMapping, instances []string, vpcID string, tags map[string]string, tgName ...string) (*elbv2.TargetGroup, error) {
 	dirty := false
 	expectedTargets := c.computeTargetGroupExpectedTargets(instances, mapping.TrafficPort)
 	if targetGroup == nil {
@@ -597,6 +619,10 @@ func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName ty
 			// HealthCheckTimeoutSeconds:  Currently not configurable, 6 seconds for HTTP, 10 for TCP/HTTPS
 		}

+		if len(tgName) > 0 {
+			input.Name = aws.String(tgName[0])
+		}
+
 		if mapping.HealthCheckConfig.Protocol != elbv2.ProtocolEnumTcp {
 			input.HealthCheckPath = aws.String(mapping.HealthCheckConfig.Path)
 		}
@@ -622,6 +648,21 @@ func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName ty
 		return tg, nil
 	}

+	{
+		if *targetGroup.Protocol != mapping.TrafficProtocol {
+			_, err := c.elbv2.DeleteTargetGroup(&elbv2.DeleteTargetGroupInput{TargetGroupArn: targetGroup.TargetGroupArn})
+			if err != nil {
+				return nil, err
+			}
+
+			var targetGroupName string
+			if len(tgName) > 0 {
+				targetGroupName = tgName[0]
+			}
+			return c.ensureTargetGroup(targetGroup, serviceName, mapping, instances, vpcID, tags, targetGroupName)
+		}
+	}
+
 	// handle instances in service
 	{
 		tgARN := aws.StringValue(targetGroup.TargetGroupArn)
